﻿
// CoreGLView.cpp: CCoreGLView 类的实现
//

#include "stdafx.h"
// SHARED_HANDLERS 可以在实现预览、缩略图和搜索筛选器句柄的
// ATL 项目中进行定义，并允许与该项目共享文档代码。
#ifndef SHARED_HANDLERS
#include "CoreGL.h"
#endif

#include "CoreGLDoc.h"
#include "CoreGLView.h"
#include <GL/freeglut.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif

GLfloat LightAmbient[] = { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat LightDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
GLfloat LightPosition[] = { 0.0f, 0.0f, 0.0f, 1.0f };

GLfloat LightAmbient2[] = { 0.2f, 0.2f, 0.2f, 1.0f };
GLfloat LightDiffuse2[] = { 0.5f, 0.5f, 0.5f, 1.0f };
//GLfloat LightPosition2[] = {0.0f, 0.0f, 2.0f, 1.0f};
GLfloat LightPosition2[] = { -2.0f, 3.0f, -2.0f, 1.0f };
// CCoreGLView

IMPLEMENT_DYNCREATE(CCoreGLView, CView)

BEGIN_MESSAGE_MAP(CCoreGLView, CView)
	// 标准打印命令
	ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_WM_SIZE()
//	ON_WM_TIMER()
ON_WM_TIMER()
ON_WM_MOUSEWHEEL()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()

// CCoreGLView 构造/析构

CCoreGLView::CCoreGLView() noexcept
{
	// TODO: 在此处添加构造代码
	iCometAngle = 0;
	iCometPos = 0;
	m_viewdist = 3;
	m_viewdir = 0;
	m_viewht = 20;

}

CCoreGLView::~CCoreGLView()
{
}

BOOL CCoreGLView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: 在此处通过修改
	//  CREATESTRUCT cs 来修改窗口类或样式
	cs.style |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
	return CView::PreCreateWindow(cs);
}

// CCoreGLView 绘图

void CCoreGLView::OnDraw(CDC* /*pDC*/)
{
	CCoreGLDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;
	RenderScene();
	// TODO: 在此处为本机数据添加绘制代码
}


// CCoreGLView 打印

BOOL CCoreGLView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// 默认准备
	return DoPreparePrinting(pInfo);
}

void CCoreGLView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: 添加额外的打印前进行的初始化过程
}

void CCoreGLView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: 添加打印后进行的清理过程
}


// CCoreGLView 诊断

#ifdef _DEBUG
void CCoreGLView::AssertValid() const
{
	CView::AssertValid();
}

void CCoreGLView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CCoreGLDoc* CCoreGLView::GetDocument() const // 非调试版本是内联的
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CCoreGLDoc)));
	return (CCoreGLDoc*)m_pDocument;
}
#endif //_DEBUG


// CCoreGLView 消息处理程序


int CCoreGLView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;

	// TODO:  在此添加您专用的创建代码
	char* argv[] = { "MFC_GLUT" };
	//初始化OpenGL和设置定时器
	m_pDC = new CClientDC(this);
	SetTimer(1, 30, NULL);
	InitializeOpenGL(m_pDC);
	init();
	InitPlanets();
	return 0;
}


void CCoreGLView::OnDestroy()
{
	CView::OnDestroy();
	//删除调色板和渲染上下文、定时器
	// TODO: 在此处添加消息处理程序代码
	::wglMakeCurrent(0, 0);
	::wglDeleteContext(m_hRC);
	if (m_hPalette)
	{
		DeleteObject(m_hPalette);
		m_hPalette = NULL;
	}
	if (m_pDC)
	{
		delete m_pDC;
		m_pDC = NULL;
	}
	KillTimer(1);
}


void CCoreGLView::OnSize(UINT nType, int cx, int cy)
{
	CView::OnSize(nType, cx, cy);
	//添加窗口缩放时的图形变换函数
	glViewport(0, 0, cx, cy);
	/////////////////////////////////////////////////////////////////

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	if (cy == 0)
		cy = 1;
	gluPerspective(30, (GLfloat)cx / (GLfloat)cy, 0.01, 50.0);
	UpdateLook();
	// TODO: 在此处添加消息处理程序代码
}




BOOL CCoreGLView::InitializeOpenGL(CDC* pDC)
{
	m_pDC = pDC;
	SetupPixelFormat();
	//生成绘制描述表
	m_hRC = ::wglCreateContext(m_pDC->GetSafeHdc());
	//置当前绘制描述表
	::wglMakeCurrent(m_pDC->GetSafeHdc(), m_hRC);

	return TRUE;
}

BOOL CCoreGLView::SetupPixelFormat()
{
	PIXELFORMATDESCRIPTOR pfd = {
		sizeof(PIXELFORMATDESCRIPTOR),    // pfd结构的大小 
		1,                                // 版本号 
		PFD_DRAW_TO_WINDOW |              // 支持在窗口中绘图 
		PFD_SUPPORT_OPENGL |              // 支持 OpenGL 
		PFD_DOUBLEBUFFER,                 // 双缓存模式 
		PFD_TYPE_RGBA,                    // RGBA 颜色模式 
		24,                               // 24 位颜色深度 
		0, 0, 0, 0, 0, 0,                 // 忽略颜色位 
		0,                                // 没有非透明度缓存 
		0,                                // 忽略移位位 
		0,                                // 无累加缓存 
		0, 0, 0, 0,                       // 忽略累加位 
		32,                               // 32 位深度缓存     
		0,                                // 无模板缓存 
		0,                                // 无辅助缓存 
		PFD_MAIN_PLANE,                   // 主层 
		0,                                // 保留 
		0, 0, 0                           // 忽略层,可见性和损毁掩模 
	};
	int pixelformat;
	pixelformat = ::ChoosePixelFormat(m_pDC->GetSafeHdc(), &pfd);//选择像素格式
	::SetPixelFormat(m_pDC->GetSafeHdc(), pixelformat, &pfd);	//设置像素格式
	if (pfd.dwFlags & PFD_NEED_PALETTE)
		return FALSE;
	return TRUE;
}

//////////////////////////////////////////////////////////
//						场景绘制与渲染
//////////////////////////////////////////////////////////
BOOL CCoreGLView::RenderScene()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glLightfv(GL_LIGHT1, GL_POSITION, LightPosition);
	glLightfv(GL_LIGHT2, GL_POSITION, LightPosition2);
	DrawSun();
	DrawPlanets();
	::SwapBuffers(m_pDC->GetSafeHdc());		//交互缓冲区
	return TRUE;
}
void CCoreGLView::DrawSun()
{
	glPushMatrix();
	//glutSolidSphere(0.05, 10, 10);
	glBegin(GL_QUAD_STRIP);         //填充凸多边形
	glVertex3f(0.0f, 0.0f, 0.0f);
	glVertex3f(0.0f, 0.2f, 0.0f);
	glVertex3f(0.2f, 0.0f, 0.0f);
	glVertex3f(0.2f, 0.2f, 0.0f);
	glVertex3f(0.2f, 0.0f, -0.2f);
	glVertex3f(0.2f, 0.2f, -0.2f);
	glVertex3f(0.0f, 0.0f, -0.2f);
	glVertex3f(0.0f, 0.2f, -0.2f);
	glVertex3f(0.0f, 0.0f, 0.0f);
	glVertex3f(0.0f, 0.2f, 0.0f);
	glEnd();
	glBegin(GL_QUAD_STRIP);
	glVertex3f(0.0f, 0.0f, 0.0f);
	glVertex3f(0.2f, 0.0f, 0.0f);
	glVertex3f(0.0f, 0.0f, -0.2f);
	glVertex3f(0.2f, 0.0f, -0.2f);
	glVertex3f(0.0f, 0.2f, 0.0f);
	glVertex3f(0.2f, 0.2f, 0.0f);
	glVertex3f(0.0f, 0.2f, -0.2f);
	glVertex3f(0.2f, 0.2f, -0.2f);
	glEnd();
	
	glPopMatrix();
}
void CCoreGLView::DrawPlanets()
{
	glEnable(GL_TEXTURE_2D);
	int i;
	for (i = 0; i < NUM_PLANETS; i++)
	{
		glBindTexture(GL_TEXTURE_2D, texture_id[m_planet[i].m_TextureID]);
		m_planet[i].Draw();
	}
	glDisable(GL_TEXTURE_2D);
}

void CCoreGLView::init(void)
{
	glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);
	glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);
	glLightfv(GL_LIGHT1, GL_POSITION, LightPosition);
	glEnable(GL_LIGHT1);

	glLightfv(GL_LIGHT2, GL_AMBIENT, LightAmbient2);
	glLightfv(GL_LIGHT2, GL_DIFFUSE, LightDiffuse2);
	glLightfv(GL_LIGHT2, GL_POSITION, LightPosition2);

	glEnable(GL_LIGHT2);

	glClearColor(0, 0, 0, 0);
	glShadeModel(GL_SMOOTH);

	glEnable(GL_DEPTH_TEST);
	glEnable(GL_LIGHTING);
	glEnable(GL_CULL_FACE);

	m_Textures.LoadTextures(texture_id, MAX_NO_TEXTURES);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}
void CCoreGLView::InitPlanets()
{
	
	m_planet[EARTH1].SetPara(0.09, 16, 0.1, 0.1, 0.2, 0, 45, 2, 0.9973, 365.2422);
	m_planet[EARTH2].SetPara(0.09, 16, 0.1, 0.1, -0.4, 0, 45, 2, 0.9973, 365.2422);
	m_planet[EARTH3].SetPara(0.09, 16, 0.1, 0.28, -0.1, 0, 45, 2, 0.9973, 365.2422);
	m_planet[EARTH4].SetPara(0.09, 16, 0.4, 0.125, -0.1, 0, 45, 2, 0.9973, 365.2422);
	m_planet[EARTH5].SetPara(0.09, 16, -0.2, 0.125, -0.1, 0, 45, 2, 0.9973, 365.2422);
	/*m_planet[EARTH3].SetPara(0.18, 16, 0, 0, 2.5, 0, 135, 6, 0.646, 30685);
	m_planet[EARTH4].SetPara(0.2, 16, 0, 0, 3.3, 0, 0, 7, 0.658, 60190);
	m_planet[EARTH5].SetPara(0.05, 16, 0, 0, 3.9, 0, 180, 8, 6.387, 248 * 365);*/
}
void CCoreGLView::rotate()
{
	int i;
	// comet
	for (i = 0; i < NUM_PLANETS; i++)
		m_planet[i].Rotate(ROTATION_SPEED);
}
void CCoreGLView::UpdateLook()
{
	double dir, ang, x, y, z, r;

	dir = m_viewdir / 180 * PI;
	ang = m_viewht / 180 * PI;
	y = m_viewdist * sin(ang);
	r = m_viewdist * cos(ang);
	x = r * cos(dir);
	z = r * sin(dir);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(x, y, z, 0, 0, 0, 0, 1, 0);
}

void CCoreGLView::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	Invalidate(FALSE);
	rotate();
	CView::OnTimer(nIDEvent);
}


BOOL CCoreGLView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	m_viewdist *= (1 - zDelta / 1000.0);
	if (m_viewdist < 0.5)
		m_viewdist = 0.5;

	UpdateLook();
	return CView::OnMouseWheel(nFlags, zDelta, pt);
}


void CCoreGLView::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	lastx = point.x;
	lasty = point.y;
	draging = 1;
	CView::OnLButtonDown(nFlags, point);
}
void CCoreGLView::UpdateViewDir(CPoint point)
{
	int dx = point.x - lastx;
	int dy = point.y - lasty;
	m_viewdir += dx / 20.0;
	if (m_viewdir > 360)
		m_viewdir -= 360;
	else if (m_viewdir < 0)
		m_viewdir += 360;

	m_viewht += dy / 20.0;
	if (m_viewht < -45)
		m_viewht = -45;
	else if (m_viewht > 45)
		m_viewht = 45;

	UpdateLook();
}


void CCoreGLView::OnLButtonUp(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if (draging)
	{
		UpdateViewDir(point);
		draging = 0;
	}
	CView::OnLButtonUp(nFlags, point);
}


void CCoreGLView::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if (draging)
	{
		UpdateViewDir(point);
		lastx = point.x;
		lasty = point.y;
	}
	CView::OnMouseMove(nFlags, point);
}
